/*
 * Copyright (c) xiake6. All Rights Reserved.
 * @Owner:fenglibin
 * @Date:  2017-11-06 11:38
 */
package net.xiake6.springcloud.gateway.filter;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;

import com.google.common.base.Strings;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;

import feign.FeignException;
import net.xiake6.springcloud.commons.enums.ApiMsgEnum;
import net.xiake6.springcloud.commons.util.json.JsonUtil;
import net.xiake6.springcloud.commons.vo.BaseReturnVO;
import net.xiake6.springcloud.gateway.common.Constants;
import net.xiake6.springcloud.gateway.service.AuthService;
import net.xiake6.springcloud.gateway.vo.PermissVO;
import net.xiake6.springcloud.gateway.vo.UserLoginVO;

/**
 * 访问授权校验.
 *
 * @author: fenglibin
 * @date: 2017-11-06 11:38
 */
public class AccessFilter extends ZuulFilter {


  private static Logger logger = LoggerFactory.getLogger(AccessFilter.class);

  @Autowired
  private AuthService authService;

  @Override
  public String filterType() {
    return "pre";
  }

  @Override
  public int filterOrder() {
    return 0;
  }

  @Override
  public boolean shouldFilter() {
    return true;
  }

  /**
   * 获取当前用户的token
   * <p>
   * 提取优先级 parameter > header > cookie
   * 三个地方都没有token，则抛出没有登录用户异常
   * </p>
   */
  @Override
  public Object run() {
    RequestContext ctx = RequestContext.getCurrentContext();
    HttpServletRequest request = ctx.getRequest();
    if (authService.checkWhitePaths(request.getRequestURI())) {
      return null;
    }
    String accessToken = request.getParameter(Constants.QUERY_TOKEN_KEY);
    if (Strings.isNullOrEmpty(accessToken)) {
      accessToken = request.getHeader(Constants.HEADER_TOKEN_KEY);
    }

    String requestURI = "";
    String requestUrl ="";
    String userAgent = "";
    if (ctx.getRequest() != null ) {
        if(ctx.getRequest().getRequestURI() != null){
            requestURI = ctx.getRequest().getRequestURI().replaceFirst("/api", "");
        }
        requestUrl = ctx.getRequest().getRequestURL().toString();
        userAgent = ctx.getRequest().getHeader(Constants.REQUEST_USER_AGENT);
      
    }
    String responseBody = "";
    ctx.set("requestTime", System.currentTimeMillis());
    ctx.setSendZuulResponse(false);
    ctx.getResponse().setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
    if (Strings.isNullOrEmpty(accessToken)) {
      logger.warn("access_token is empty");
      ctx.setResponseStatusCode(HttpStatus.OK.value());
      responseBody = "{\"result\":-1,\"msg\":\"缺少access_token\"}";
    } else {
      Integer userId = 0;
      try {
        BaseReturnVO verifyResut = authService.verifyToken(accessToken, requestURI,requestUrl,userAgent);
        
        if (verifyResut != null && ApiMsgEnum.UNAUTHORIZED.getResCode() == verifyResut
            .getResult()) {
          ctx.setResponseStatusCode(HttpStatus.OK.value());
          ctx.addZuulRequestHeader(Constants.HEADER_USER_KEY, "0");
          ctx.set(Constants.HEADER_USER_KEY, 0);
          PermissVO loginOutVO = new PermissVO();
          loginOutVO.setMsg(verifyResut.getMsg());
          loginOutVO.setResult(ApiMsgEnum.UNAUTHORIZED.getResCode());
          responseBody = JsonUtil.toJSON(loginOutVO);
          ctx.setResponseBody(responseBody);
          return null;

        } else if (verifyResut != null && verifyResut.getResult() == ApiMsgEnum.OK.getResCode()) {
          UserLoginVO userLoginVO = JsonUtil.fromJSON(verifyResut, UserLoginVO.class);
          userId = userLoginVO.getUserId();
        }
        if (userId > 0) {
          ctx.setSendZuulResponse(true);
          ctx.addZuulRequestHeader(Constants.HEADER_USER_KEY, String.valueOf(userId));
          ctx.set(Constants.HEADER_USER_KEY, userId);
          logger.trace("access token {} ok, userId {}", accessToken, userId);
          return null;
        } else {
          ctx.setResponseStatusCode(HttpStatus.OK.value());
          ctx.addZuulRequestHeader(Constants.HEADER_USER_KEY, "0");
          ctx.set(Constants.HEADER_USER_KEY, 0);
          logger.info("accessToken [{}]  Invalid ", accessToken);
          PermissVO loginOutVO = new PermissVO();
          loginOutVO.setMsg("身份授权已过期，请重新登录");
          loginOutVO.setIsLogOut(1);
          loginOutVO.setIsPower(0);
          loginOutVO.setResult(-1);
          responseBody = JsonUtil.toJSON(loginOutVO);
        }
      } catch (FeignException feignException) {
        ctx.setSendZuulResponse(false);
        ctx.setResponseStatusCode(HttpStatus.OK.value());
        ctx.setResponseBody(new String(feignException.content()));
        logger.error("api-gateway Exception", feignException);
        return null;
      } catch (Exception e) {
        ctx.setSendZuulResponse(false);
        ctx.setResponseStatusCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
        ctx.setResponseBody(e.getMessage());
        logger.error("api-gateway Exception", e);
        return null;
      }

    }
    ctx.setResponseBody(responseBody);
    return null;

  }

}

